﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace huqiang.Collections
{
    public class LockQueueS<T> where T : struct, IClear
    {
        int start = 0;
        int end = 0;
        T[] buffer;
        int mlen;
        SpinLock spin = new SpinLock();
        public LockQueueS(int len = 2048)
        {
            buffer = new T[len];
            mlen = len;
        }
        public int BufferLenth { get { return mlen; } }
        public int Count
        {
            get
            {
                if (end == start)
                    return 0;
                bool gotLock = false;
                try
                {
                    spin.Enter(ref gotLock);
                    int a = end - start;
                    if (a < 0)
                        a += mlen;
                    return a;
                }
                finally
                {
                    if (gotLock)
                        spin.Exit();
                }
            }
        }
        public bool Enqueue(T t)
        {
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);
                int e = end + 1;
                if (e >= mlen)
                    e = 0;
                if (e == start)//缓存已满
                    return false;
                buffer[end] = t;
                end = e;
                return true;
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
        }
        public T Dequeue()
        {
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);
                if (start != end)
                {
                    int a = start;
                    T t = buffer[a];
                    if (start >= mlen - 1)
                        start = 0;
                    else start++;
                    buffer[a].Clear();
                    return t;
                }
                return new T();
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
        }

        public bool Dequeue(ref T t)
        {
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);
                if (start != end)
                {
                    int a = start;
                    t = buffer[a];
                    if (start >= mlen - 1)
                        start = 0;
                    else start++;
                    buffer[a].Clear();
                    return true;
                }
                return false;
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
        }
        public void Clear()
        {
            bool gotLock = false;
            try
            {
                spin.Enter(ref gotLock);
                if (start != end)
                {
                    int len = end - start;
                    if (len < 0)
                        len += mlen;
                    for (int i = 0; i < len; i++)
                    {
                        buffer[start].Clear();
                        start++;
                        if (start >= mlen)
                            start = 0;
                    }
                    start = end = 0;
                }
            }
            finally
            {
                if (gotLock)
                    spin.Exit();
            }
            start = end;
        }
    }
}
